#include "cJSON.h"
#include "cmsis_os2.h"
#include "socket.h"
#include <pthread.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define PORT 8088
#define BUFFER_SIZE 1024
#define BOARD_SIZE 9

static osThreadId_t g_tid = NULL;

int chessBoard[BOARD_SIZE][BOARD_SIZE] = {0};
pthread_mutex_t board_mutex = PTHREAD_MUTEX_INITIALIZER;

int placePiece(int row, int col, int pieceNumber) {
    if (row < 0 || row >= BOARD_SIZE || col < 0 || col >= BOARD_SIZE || pieceNumber < 0 || pieceNumber > 9) {
        return -1;
    }
    chessBoard[row][col] = pieceNumber;
    return 0;
}

int getPiece(int row, int col) {
    if (row < 0 || row >= BOARD_SIZE || col < 0 || col >= BOARD_SIZE) {
        return -1;
    }
    return chessBoard[row][col];
}

int isBoardFullyFilled() {
    pthread_mutex_lock(&board_mutex);
    for (int i = 0; i < BOARD_SIZE; i++) {
        for (int j = 0; j < BOARD_SIZE; j++) {
            if (chessBoard[i][j] == 0) {
                pthread_mutex_unlock(&board_mutex);
                return 0;
            }
        }
    }
    pthread_mutex_unlock(&board_mutex);
    return 1;
}

int verifyBoardWithAnswer(const char *answer) {
    pthread_mutex_lock(&board_mutex);
    for (int i = 0; i < BOARD_SIZE; i++) {
        for (int j = 0; j < BOARD_SIZE; j++) {
            int piece = chessBoard[i][j];
            int answerPiece = answer[i * BOARD_SIZE + j] - '0';
            if (piece != answerPiece) {
                pthread_mutex_unlock(&board_mutex);
                return 0;
            }
        }
    }
    pthread_mutex_unlock(&board_mutex);
    return 1;
}

void *listenBoardStatus(void *arg) {
    const char *answer = (const char *)arg;
    while (1) {
        if (isBoardFullyFilled()) {
            printf("liuboyi Board is fully filled. Verifying...\n");
            if (verifyBoardWithAnswer(answer)) {
                printf("liuboyi Board is correctly filled according to the answer.\n");
            } else {
                printf("liuboyi Board is filled, but does not match the answer.\n");
            }
            break;
        }
        sleep(1);
    }
    return NULL;
}

int fillBoardWithQuestion(const char *question) {
    if (strlen(question) != 81) {
        return -1;
    }

    for (int i = 0; i < 81; i++) {
        int row = i / 9;
        int col = i % 9;
        int pieceNumber = question[i] - '0';
        if (placePiece(row, col, pieceNumber) == -1) {
            return -1;
        }
    }
    return 0;
}

char *parse_json_to_c_string(const char *json_data) {
    cJSON *json = cJSON_Parse(json_data);
    if (json == NULL) {
        const char *error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL) {
            fprintf(stderr, "Error before: %s\n", error_ptr);
        }
        return strdup("Invalid JSON data");
    }

    cJSON *problem = cJSON_GetObjectItemCaseSensitive(json, "problem");
    cJSON *question = cJSON_GetObjectItemCaseSensitive(json, "question");
    cJSON *answer = cJSON_GetObjectItemCaseSensitive(json, "answer");

    if (!cJSON_IsNumber(problem) || !cJSON_IsString(question) || !cJSON_IsString(answer)) {
        cJSON_Delete(json);
        return strdup("Invalid JSON data: missing or invalid fields");
    }

    if (strlen(question->valuestring) != 81 || strlen(answer->valuestring) != 81) {
        cJSON_Delete(json);
        return strdup("Invalid JSON data: question or answer length is not 81");
    }

    if (fillBoardWithQuestion(question->valuestring) == -1) {
        cJSON_Delete(json);
        return strdup("Failed to place pieces on the board");
    }

    char *result = (char *)malloc(256 * sizeof(char));
    if (result == NULL) {
        cJSON_Delete(json);
        return strdup("Memory allocation failed");
    }

    snprintf(result, 256, "Problem: %d\nQuestion: %s\nAnswer: %s",
            